package com.hd123.rumba.qt.report;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.sf.jasperreports.engine.JRAlignment;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRElement;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRExpressionChunk;
import net.sf.jasperreports.engine.JRGraphicElement;
import net.sf.jasperreports.engine.JRResultSetDataSource;
import net.sf.jasperreports.engine.JRVariable;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.design.JRDesignBand;
import net.sf.jasperreports.engine.design.JRDesignDataset;
import net.sf.jasperreports.engine.design.JRDesignExpression;
import net.sf.jasperreports.engine.design.JRDesignExpressionChunk;
import net.sf.jasperreports.engine.design.JRDesignField;
import net.sf.jasperreports.engine.design.JRDesignStaticText;
import net.sf.jasperreports.engine.design.JRDesignTextField;
import net.sf.jasperreports.engine.design.JRDesignVariable;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JExcelApiExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

/**
 * 使用方法见文件尾部的main(String[]), 适用于QT的打印和非QT的打印. <br>
 * 在查询工具中的用例如下:
 * <li>打印:
 * <li>1.提示打印范围: 全部记录, 第x-x条记录, 当前页的记录. 输出格式:HTML,PDF,EXCEL. 如果没有打印格式定义文件,
 * 还提示要打印字段. 打印格式定义文件是和查询定义文件同名的.jrxml文件, 可使用iReport制作或手工编写
 * <li>2.如果记录数超过1000条, 提示仅打印从x开始的1000条记录.
 * <li>3.生成报表的输入参数: 查询结果集, 打印格式定义文件, 标题, 子标题, 页面定义, 字段定义,
 * <li>4.生成打印页面
 * 
 * @author caili
 * @since 2006-7-13
 * 
 */
public class Report {
  /**
   * 数据集
   */
  private ResultSet dataSource = null;
  /**
   * 打印格式定义文件, jrxml. 如果提供了, 则在build的时候, 使用此格式, <br>
   * 而不根据以下的属性来生成格式
   */
  private File designFile = null;
  /**
   * 报表标题. 当designFile==null时使用.
   */
  private String reportTitle = "报表标题";
  /**
   * 报表子标题. 当designFile==null时使用. 当reportSubtitle != null时显示.
   */
  private String reportSubtitle = null;
  /**
   * 纸张定义. 当designFile==null时使用.
   */
  private PaperDefinition paper = new PaperDefinition();
  /**
   * 字段定义. 当designFile==null时使用.
   */
  private List<FieldDefinition> fieldDefinition = null;
  /**
   * 是否显示序号列. 当designFile==null时使用.
   */
  private boolean showNumberColumn = true;

  /**
   * 内部使用, build()过程生成
   */
  private JasperPrint print = null;

  public void build() throws JRException {
    build(1, 1000);
  }

  /**
   * @param start
   *            1-based
   * @param limit
   *            记录条数
   * @throws JRException
   */
  public void build(int start, int limit) throws JRException {
    JasperDesign design = createDesign();
    JasperReport report = JasperCompileManager.compileReport(design);
    JRDataSource ds = new JRResultSetDataSource(
        new ResultSetLimitedFacade(dataSource, start, limit));
    print = JasperFillManager.fillReport(report, null, ds);
  }

  /**
   * 生成打印样式. 要保存成文件的话, 可调用<br>
   * JRXmlWriter.writeReport(createDesign(), outputStream, "utf-8");<br>
   * 要从xml文件中装载的话, 可调用<br>
   * JasperDesign designLoaded = JRXmlLoader.load("c:/temp/test.jrxml");
   * 
   * @return
   * @throws JRException
   */
  public JasperDesign createDesign() throws JRException {
    if (getDesignFile() != null)
      return JRXmlLoader.load(getDesignFile());

    int nw = 30; // 序号列宽度;
    int titleFontSize = 12;
    int fontSize = 9;

    // design
    JasperDesign design = new JasperDesign();
    design.setName("qtreport");
    if (paper.getPageWidth() != 0)
      design.setPageWidth(paper.getPageWidth());
    if (paper.getPageHeight() != 0)
      design.setPageHeight(paper.getPageHeight());
    if (paper.getLeftMargin() != 0)
      design.setLeftMargin(paper.getLeftMargin());
    if (paper.getTopMargin() != 0)
      design.setTopMargin(paper.getTopMargin());
    if (paper.getRightMargin() != 0)
      design.setRightMargin(paper.getRightMargin());
    if (paper.getBottomMargin() != 0)
      design.setBottomMargin(paper.getBottomMargin());

    // 计算columnWidth
    {
      int a = design.getPageWidth() - design.getLeftMargin() - design.getRightMargin() - 2;
      int b = a - design.getColumnSpacing() * (design.getColumnCount() - 1);
      int c = b / design.getColumnCount();
      // if (c > design.getColumnWidth())
      // 不管什么情况，都把页宽置成Column宽
      design.setColumnWidth(c - 2);
    }

    // adjust column width
    int ww = design.getColumnWidth() - (showNumberColumn ? nw : 0); // 打印区域宽度
    int fw = 0; // 字段总宽度
    for (int i = 0; i < fieldDefinition.size(); ++i)
      fw += fieldDefinition.get(i).getWidth();
    if (true || fw < ww) {
      double scale = ww * 1.0 / fw;
      fw = 0;
      for (int i = 0; i < fieldDefinition.size() - 1; ++i) {
        int w = (int) (fieldDefinition.get(i).getWidth() * scale);
        fieldDefinition.get(i).setWidth(w);
        fw += w;
      }
      fieldDefinition.get(fieldDefinition.size() - 1).setWidth(ww - fw);
    }

    // field definitions
    JRDesignDataset ds = new JRDesignDataset(true);
    for (int i = 0; i < fieldDefinition.size(); ++i) {
      JRDesignField field = new JRDesignField();
      field.setName(fieldDefinition.get(i).getName());
      field.setValueClass(fieldDefinition.get(i).getValueClass());
      ds.addField(field);
    }
    design.setMainDataset(ds);

    // title band
    JRDesignBand title = new JRDesignBand();
    // 标题每行高th, 行数tc; 子标题每行高sth, 行数stc
    int th = 20, tc = 1, sth = 16, stc = 0;
    tc = getReportTitle().split("\n").length;
    if (getReportSubtitle() != null)
      stc = getReportSubtitle().split("\n").length;
    title.setHeight(th * tc + sth * stc);
    JRDesignStaticText caption;
    caption = new JRDesignStaticText();
    caption.setX(0);
    caption.setY(0);
    caption.setWidth(design.getPageWidth());
    caption.setHeight(th * tc);
    caption.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
    caption.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_TOP);
    caption.setFontName("宋体");
    caption.setFontSize(titleFontSize);
    caption.setBold(true);
    caption.setPdfFontName("STSong-Light");
    caption.setPdfEncoding("UniGB-UCS2-H");
    caption.setMode(JRElement.MODE_TRANSPARENT);
    caption.setText(getReportTitle());
    title.addElement(caption);
    if (getReportSubtitle() != null) {
      caption = new JRDesignStaticText();
      caption.setX(0);
      caption.setY(th * tc);
      caption.setWidth(design.getPageWidth());
      caption.setHeight(sth * stc);
      caption.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_LEFT);
      caption.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_BOTTOM);
      caption.setFontName("宋体");
      caption.setFontSize(fontSize);
      caption.setPdfFontName("STSong-Light");
      caption.setPdfEncoding("UniGB-UCS2-H");
      caption.setText(getReportSubtitle());
      caption.setMode(JRElement.MODE_TRANSPARENT);
      title.addElement(caption);
    }
    design.setTitle(title);

    // column header
    JRDesignBand columnHeader = new JRDesignBand();
    columnHeader.setHeight(16);
    int x = 0;

    JRDesignStaticText columnTitle;
    // 序号列
    if (showNumberColumn) {
      columnTitle = new JRDesignStaticText();
      columnTitle.setX(x);
      columnTitle.setY(0);
      columnTitle.setWidth(nw);
      columnTitle.setHeight(columnHeader.getHeight());
      columnTitle.setLeftBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setTopBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setRightBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setBottomBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
      columnTitle.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_MIDDLE);
      columnTitle.setText("序号");
      columnTitle.setFontName("宋体");
      columnTitle.setFontSize(fontSize);
      columnTitle.setPdfFontName("STSong-Light");
      columnTitle.setPdfEncoding("UniGB-UCS2-H");
      columnHeader.addElement(columnTitle);
      x += nw;
    }
    for (int i = 0; i < fieldDefinition.size(); ++i) {
      columnTitle = new JRDesignStaticText();
      columnTitle.setX(x);
      columnTitle.setY(0);
      columnTitle.setWidth(fieldDefinition.get(i).getWidth());
      columnTitle.setHeight(columnHeader.getHeight());
      if (i == 0 && !showNumberColumn)
        columnTitle.setLeftBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setTopBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setRightBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setBottomBorder(JRGraphicElement.PEN_THIN);
      columnTitle.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
      columnTitle.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_MIDDLE);
      columnTitle.setText(fieldDefinition.get(i).getTitle());
      columnTitle.setFontName("宋体");
      columnTitle.setFontSize(fontSize);
      columnTitle.setPdfFontName("STSong-Light");
      columnTitle.setPdfEncoding("UniGB-UCS2-H");
      columnHeader.addElement(columnTitle);
      x += fieldDefinition.get(i).getWidth();
    }
    design.setColumnHeader(columnHeader);

    // detail band
    JRDesignBand detail = new JRDesignBand();
    detail.setHeight(16);
    x = 0;
    JRDesignTextField column;
    JRDesignExpression expr;
    JRDesignExpressionChunk chunk;
    JRDesignVariable var;
    // 序号列
    if (showNumberColumn) {
      column = new JRDesignTextField();
      column.setX(x);
      column.setY(0);
      column.setWidth(nw);
      column.setHeight(detail.getHeight());
      column.setPadding(2);
      column.setLeftBorder((byte) 5);
      column.setRightBorder((byte) 5);
      column.setBottomBorder((byte) 5);
      column.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
      column.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_MIDDLE);
      expr = new JRDesignExpression();
      chunk = new JRDesignExpressionChunk();
      chunk.setText(JRVariable.REPORT_COUNT);
      chunk.setType(JRExpressionChunk.TYPE_VARIABLE);
      expr.addChunk(chunk);
      expr.setValueClass(Integer.class);
      column.setExpression(expr);
      column.setFontName("宋体");
      column.setFontSize(fontSize);
      column.setPattern("0");
      column.setPdfFontName("STSong-Light");
      column.setPdfEncoding("UniGB-UCS2-H");
      detail.addElement(column);
      x += nw;
    }
    for (int i = 0; i < fieldDefinition.size(); ++i) {
      column = new JRDesignTextField();
      column.setX(x);
      column.setY(0);
      column.setWidth(fieldDefinition.get(i).getWidth());
      column.setHeight(detail.getHeight());
      column.setPadding(2);
      if (!showNumberColumn && i == 0)
        column.setLeftBorder((byte) 5);
      column.setRightBorder((byte) 5);
      column.setBottomBorder((byte) 5);
      if (Number.class.isAssignableFrom(fieldDefinition.get(i).getValueClass()))
        column.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_RIGHT);
      else if (Date.class.isAssignableFrom(fieldDefinition.get(i).getValueClass()))
        column.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
      else
        column.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_LEFT);
      column.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_MIDDLE);
      expr = new JRDesignExpression();
      chunk = new JRDesignExpressionChunk();
      chunk.setText(fieldDefinition.get(i).getName());
      chunk.setType(JRExpressionChunk.TYPE_FIELD);
      expr.addChunk(chunk);
      expr.setValueClass(fieldDefinition.get(i).getValueClass());
      column.setExpression(expr);
      column.setFontName("宋体");
      column.setFontSize(fontSize);
      column.setPattern(fieldDefinition.get(i).getPattern());
      column.setPdfFontName("STSong-Light");
      column.setPdfEncoding("UniGB-UCS2-H");
      detail.addElement(column);
      x += fieldDefinition.get(i).getWidth();
    }
    design.setDetail(detail);

    // summary band
    JRDesignBand summary = new JRDesignBand();
    summary.setHeight(16);
    x = 0;
    // 累计列,显示在序号列上
    if (showNumberColumn) {
      caption = new JRDesignStaticText();
      caption.setX(x);
      caption.setY(0);
      caption.setWidth(nw);
      caption.setHeight(summary.getHeight());
      caption.setPadding(2);
      caption.setLeftBorder((byte) 5);
      caption.setTopBorder((byte) 5);
      caption.setRightBorder((byte) 5);
      caption.setBottomBorder((byte) 5);
      caption.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
      caption.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_MIDDLE);
      caption.setText("累计:");
      caption.setFontName("宋体");
      caption.setFontSize(fontSize);
      caption.setBold(true);
      caption.setPdfFontName("STSong-Light");
      caption.setPdfEncoding("UniGB-UCS2-H");
      summary.addElement(caption);
      x += nw;
    }
    for (int i = 0; i < fieldDefinition.size(); ++i) {
      if (fieldDefinition.get(i).getGAggregationCalculation() != JRVariable.CALCULATION_NOTHING) {
        column = new JRDesignTextField();
        column.setX(x);
        column.setY(0);
        column.setWidth(fieldDefinition.get(i).getWidth());
        column.setHeight(summary.getHeight());
        column.setPadding(2);
        if (!showNumberColumn && i == 0)
          column.setLeftBorder((byte) 5);
        column.setTopBorder((byte) 5);
        column.setRightBorder((byte) 5);
        column.setBottomBorder((byte) 5);
        if (Number.class.isAssignableFrom(fieldDefinition.get(i).getValueClass()))
          column.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_RIGHT);
        else if (Date.class.isAssignableFrom(fieldDefinition.get(i).getValueClass()))
          column.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
        else
          column.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_LEFT);
        column.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_MIDDLE);
        chunk = new JRDesignExpressionChunk();
        chunk.setText(fieldDefinition.get(i).getName());
        chunk.setType(JRExpressionChunk.TYPE_FIELD);
        expr = new JRDesignExpression();
        expr.addChunk(chunk);
        expr.setValueClass(fieldDefinition.get(i).getValueClass());
        var = new JRDesignVariable();
        var.setName("SUMMARY" + fieldDefinition.get(i).getName());
        var.setExpression(expr);
        var.setCalculation(JRVariable.CALCULATION_SUM);
        var.setValueClass(fieldDefinition.get(i).getValueClass());
        design.addVariable(var);
        chunk = new JRDesignExpressionChunk();
        chunk.setText("SUMMARY" + fieldDefinition.get(i).getName());
        chunk.setType(JRExpressionChunk.TYPE_VARIABLE);
        expr = new JRDesignExpression();
        expr.addChunk(chunk);
        expr.setValueClass(fieldDefinition.get(i).getValueClass());
        column.setExpression(expr);
        column.setFontName("宋体");
        column.setFontSize(fontSize);
        column.setBold(true);
        column.setPattern(fieldDefinition.get(i).getPattern());
        column.setPdfFontName("STSong-Light");
        column.setPdfEncoding("UniGB-UCS2-H");
        summary.addElement(column);
      } else {
        // 空白
        caption = new JRDesignStaticText();
        caption.setX(x);
        caption.setY(0);
        caption.setWidth(fieldDefinition.get(i).getWidth());
        caption.setHeight(summary.getHeight());
        caption.setPadding(2);
        if (!showNumberColumn && i == 0)
          caption.setLeftBorder((byte) 5);
        caption.setTopBorder((byte) 5);
        caption.setRightBorder((byte) 5);
        caption.setBottomBorder((byte) 5);
        caption.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
        caption.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_MIDDLE);
        caption.setText(" ");
        caption.setFontName("宋体");
        caption.setFontSize(fontSize);
        caption.setBold(true);
        caption.setPdfFontName("STSong-Light");
        caption.setPdfEncoding("UniGB-UCS2-H");
        summary.addElement(caption);
      }
      x += fieldDefinition.get(i).getWidth();
    }
    design.setColumnFooter(summary);

    // page footer
    JRDesignBand pageFooter = new JRDesignBand();
    pageFooter.setHeight(20);
    int w = 20;
    x = (design.getPageWidth() - w * 3) / 2;
    JRDesignStaticText leftHyphen = new JRDesignStaticText();
    leftHyphen.setX(x);
    leftHyphen.setY(0);
    leftHyphen.setWidth(w);
    leftHyphen.setHeight(pageFooter.getHeight());
    leftHyphen.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
    leftHyphen.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_BOTTOM);
    leftHyphen.setFontName("宋体");
    leftHyphen.setFontSize(fontSize);
    leftHyphen.setText("-");
    pageFooter.addElement(leftHyphen);

    x += w;
    JRDesignTextField pageNumber = new JRDesignTextField();
    pageNumber.setX(x);
    pageNumber.setY(0);
    pageNumber.setWidth(w);
    pageNumber.setHeight(pageFooter.getHeight());
    pageNumber.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
    pageNumber.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_BOTTOM);
    pageNumber.setFontName("宋体");
    pageNumber.setFontSize(fontSize);
    expr = new JRDesignExpression();
    chunk = new JRDesignExpressionChunk();
    chunk.setText(JRVariable.PAGE_NUMBER);
    chunk.setType(JRExpressionChunk.TYPE_VARIABLE);
    expr.addChunk(chunk);
    expr.setValueClass(Integer.class);
    pageNumber.setExpression(expr);
    pageFooter.addElement(pageNumber);

    x += w;
    JRDesignStaticText rightHyphen = new JRDesignStaticText();
    rightHyphen.setX(x);
    rightHyphen.setY(0);
    rightHyphen.setWidth(w);
    rightHyphen.setHeight(pageFooter.getHeight());
    rightHyphen.setHorizontalAlignment(JRAlignment.HORIZONTAL_ALIGN_CENTER);
    rightHyphen.setVerticalAlignment(JRAlignment.VERTICAL_ALIGN_BOTTOM);
    rightHyphen.setFontName("宋体");
    rightHyphen.setFontSize(fontSize);
    rightHyphen.setText("-");
    pageFooter.addElement(rightHyphen);
    design.setPageFooter(pageFooter);

    return design;
  }

  public void exportToPdf(String fileName) throws JRException, FileNotFoundException {
    File file = new File(fileName);
    file.getParentFile().mkdirs();
    FileOutputStream out = new FileOutputStream(file);
    exportToPdf(out);
  }

  public void exportToPdf(OutputStream out) throws JRException {
    JRExporter exporter = new JRPdfExporter();
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
    exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
    exporter.exportReport();
  }

  public void exportToHtml(String fileName) throws JRException, FileNotFoundException {
    File file = new File(fileName);
    file.getParentFile().mkdirs();
    FileOutputStream out = new FileOutputStream(file);
    exportToHtml(out);
  }

  public void exportToHtml(OutputStream out) throws JRException {
    JRExporter exporter = new JRHtmlExporter();
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
    exporter.setParameter(JRHtmlExporterParameter.IS_WRAP_BREAK_WORD, Boolean.FALSE);
    exporter.setParameter(JRHtmlExporterParameter.SIZE_UNIT,
        JRHtmlExporterParameter.SIZE_UNIT_POINT);
    exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN, Boolean.FALSE);
    exporter.setParameter(JRHtmlExporterParameter.BETWEEN_PAGES_HTML,
        "<br style='page-break-before:always;'>");
    exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
    exporter.exportReport();
  }

  public void exportToExcel(String fileName) throws JRException, FileNotFoundException {
    File file = new File(fileName);
    file.getParentFile().mkdirs();
    FileOutputStream out = new FileOutputStream(file);
    exportToExcel(out);
  }

  public void exportToExcel(OutputStream out) throws JRException {
    JRExporter exporter = new JExcelApiExporter();
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
    exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
    exporter.setParameter(JRXlsExporterParameter.IS_AUTO_DETECT_CELL_TYPE, Boolean.FALSE);
    exporter.exportReport();
  }

  public ResultSet getDataSource() {
    return dataSource;
  }

  public void setDataSource(ResultSet dataSource) {
    this.dataSource = dataSource;
  }

  public List<FieldDefinition> getFieldDefinition() {
    return fieldDefinition;
  }

  public void setFieldDefinition(List<FieldDefinition> fieldDefinition) {
    this.fieldDefinition = fieldDefinition;
  }

  public PaperDefinition getPaper() {
    return paper;
  }

  public void setPaper(PaperDefinition paper) {
    this.paper = paper;
  }

  public File getDesignFile() {
    return designFile;
  }

  public void setDesignFile(File designFile) {
    this.designFile = designFile;
  }

  public String getReportTitle() {
    return reportTitle;
  }

  public void setReportTitle(String reportTitle) {
    this.reportTitle = reportTitle;
  }

  public boolean isShowNumberColumn() {
    return showNumberColumn;
  }

  public void setShowNumberColumn(boolean showNumberColumn) {
    this.showNumberColumn = showNumberColumn;
  }

  public String getReportSubtitle() {
    return reportSubtitle;
  }

  public void setReportSubtitle(String reportSubtitle) {
    this.reportSubtitle = reportSubtitle;
  }

  public static void main(String[] args) throws Exception {
    System.out.println("==开始==");
    System.out.println("建立数据库连接");
    DriverManager.registerDriver((Driver) Class.forName("oracle.jdbc.driver.OracleDriver")
        .newInstance());
    Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:tango",
        "tango", "tango");
    Statement stmt = conn.createStatement();

    for (int i = 0; i < 1; ++i) {
      Date st = new Date();
      System.out.println("执行查询, 取得结果集");
      ResultSet rs = stmt
          .executeQuery("select BILLTYPE, billnumber, TOTAL, lastmodified, buyername, sellername "
              + "from torder where billnumber like 'SHDC200603%' order by billNumber");

      System.out.println("定义字段");
      List fields = new ArrayList();
      FieldDefinition field = new FieldDefinition();
      field.setTitle("单据类型");
      field.setName("BILLTYPE");
      field.setValueClass(String.class);
      field.setWidth(100);
      field.setPattern("");
      fields.add(field);

      field = new FieldDefinition();
      field.setTitle("单号");
      field.setName("BILLNUMBER");
      field.setValueClass(String.class);
      field.setWidth(100);
      field.setPattern("");
      fields.add(field);

      field = new FieldDefinition();
      field.setTitle("金额");
      field.setName("TOTAL");
      field.setValueClass(BigDecimal.class);
      field.setWidth(100);
      field.setPattern("#,##0.00");
      fields.add(field);

      field = new FieldDefinition();
      field.setTitle("日期");
      field.setName("LASTMODIFIED");
      field.setValueClass(Date.class);
      field.setWidth(100);
      field.setPattern("yyyy-MM-dd");
      fields.add(field);

      System.out.println("制作报表");
      Report report = new Report();
      report.setDataSource(rs);
      report.setReportTitle("TORDER\n单据");
      report.setReportSubtitle("打印时间: "
          + new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()) + "\n第2行\n第3行\n第4行"); // 可选
      report.setPaper(new PaperDefinition());
      report.setFieldDefinition(fields);
      report.build(3, 1000); // 从第3条记录开始, 最多打印1000条记录. 可选不带参数的build()
      System.out.println("生成htm");
      report.exportToHtml("c:/temp/report" + i + ".htm");
      System.out.println("生成pdf");
      report.exportToPdf("c:/temp/report" + i + ".pdf");
      System.out.println("生成excel");
      report.exportToExcel("c:/temp/report" + i + ".xls");

      rs.close();
      System.out.println("用时: " + (new Date().getTime() - st.getTime()));
    }

    stmt.close();
    conn.close();

    System.out.println("==完成==");
  }

}
